package com.songlanyun.modules.ship.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.songlanyun.common.enums.LockPrefixConstant;
import com.songlanyun.common.enums.OrderConstant;
import com.songlanyun.common.enums.ShopGainsConstant;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.lock.DistributedLock;
import com.songlanyun.common.utils.DateUtils;
import com.songlanyun.common.utils.OrderGen;
import com.songlanyun.common.validator.ValidatorUtils;
import com.songlanyun.modules.exception.OrderException;
import com.songlanyun.modules.gains.service.ShopGainsBillService;
import com.songlanyun.modules.logisticscompany.entity.SystemLogisticsCompanyEntity;
import com.songlanyun.modules.logisticscompany.service.SystemLogisticsCompanyService;
import com.songlanyun.modules.logisticsconfig.entity.LogisticsConfig;
import com.songlanyun.modules.logisticsconfig.service.LogisticsConfigService;
import com.songlanyun.modules.order.entity.ChildOrder;
import com.songlanyun.modules.order.entity.Order;
import com.songlanyun.modules.order.service.ChildOrderService;
import com.songlanyun.modules.order.service.OrderService;
import com.songlanyun.modules.rabbitmq.DelayedConstant;
import com.songlanyun.modules.rabbitmq.MqConstant;
import com.songlanyun.modules.rabbitmq.service.SendMsgService;
import com.songlanyun.modules.saleconfig.entity.SaleConfig;
import com.songlanyun.modules.saleconfig.service.SaleConfigService;
import com.songlanyun.modules.ship.entity.OrderPackageExpress;
import com.songlanyun.modules.ship.entity.OrderPackageItem;
import com.songlanyun.modules.ship.entity.OrderPackagePickup;
import com.songlanyun.modules.ship.model.dto.BranchShipVO;
import com.songlanyun.modules.ship.model.dto.ExpressShipDTO;
import com.songlanyun.modules.ship.model.dto.ShipItemDTO;
import com.songlanyun.modules.ship.service.OrderPackageExpressService;
import com.songlanyun.modules.ship.service.OrderPackageItemService;
import com.songlanyun.modules.ship.service.OrderPackagePickupService;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songlanyun.common.utils.PageUtils;
import com.songlanyun.common.utils.Query;

import com.songlanyun.modules.ship.dao.OrderPackageDao;
import com.songlanyun.modules.ship.entity.OrderPackage;
import com.songlanyun.modules.ship.service.OrderPackageService;
import org.springframework.transaction.annotation.Transactional;


@Service("orderPackageService")
public class OrderPackageServiceImpl extends ServiceImpl<OrderPackageDao, OrderPackage> implements OrderPackageService {


    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderPackageExpressService orderPackageExpressService;

    @Autowired
    private OrderPackagePickupService orderPackagePickupService;


    @Autowired
    private OrderPackageItemService orderPackageItemService;


    @Autowired
    private LogisticsConfigService logisticsConfigService;

    @Autowired
    private SaleConfigService saleConfigService;

    @Autowired
    private ChildOrderService childOrderService;


    @Autowired
    private ShopGainsBillService shopGainsBillService;

    @Autowired
    private SendMsgService sendMsgService;

    @Autowired
    private SystemLogisticsCompanyService systemLogisticsCompanyService;


    @Override
    public OrderPackage create(OrderPackage entity) {
        ValidatorUtils.validateEntity(entity);
        this.baseMapper.insert(entity);
        return entity;
    }
    @Override
    public Integer createReturnId(OrderPackage entity) {
        ValidatorUtils.validateEntity(entity);
        Integer id = this.baseMapper.insert(entity);
        return id;
    }

    @Override
    public OrderPackage modify(OrderPackage entity) {
        ValidatorUtils.validateEntity(entity);
        this.baseMapper.updateById(entity);
        return entity;
    }

    @Override
    public void remove(Long id) {

    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<OrderPackage> page = this.page(
                new Query<OrderPackage>().getPage(params),
                new QueryWrapper<OrderPackage>()
        );

        return new PageUtils(page);
    }

    /**
     * 创建物流包包裹
     *
     * @param shopId
     * @param dto
     * @return
     */
    @Transactional
    @Override
    public OrderPackage expressShip(Long shopId, ExpressShipDTO dto) {

        Order order = orderService.loadByShopIdAndId(shopId, dto.getOrderId(), true);
        OrderPackage orderPackage = buildOrderPackage(dto, order);
        //创建包裹明细
        createPackageItemsByOrder(orderPackage, order);

        //订单运费入账
        if (order.getRealFreight().compareTo(BigDecimal.ZERO) > 0) {
            shopGainsBillService.inBill(order.getShopId(),
                    ShopGainsConstant.InnerMode.FREIGHT,
                    order.getRealFreight(),
                    String.format("订单：%s,运费入账：%s元", order.getOrderCode(), order.getRealFreight().toString()), order.getOrderCode());
        }

        return orderPackage;
    }

    @NotNull
    private OrderPackage buildOrderPackage(ExpressShipDTO dto, Order order) {
        //如果是无效订单，则不能发货
        if (2 == order.getMarketingType() && !order.getEffective()) {
            throw new RRException("拼团订单只有组团成功之后才能发货");
        }

        if (OrderConstant.ShipStatus.ALREADY_SHIP.equals(order.getShipStatus())) {
            throw new RRException(OrderException.SHIP_REPEAT);
        }

        //自提订单不要用物流发货
        if (order.getShipmentMode().equals(OrderConstant.ShipmentMode.PICK_UP)) {
            throw new RRException(OrderException.PICK_UP_ORDER_NOT_EXPRESS);
        }
        //创建订单包裹
        OrderPackage orderPackage = createOrderPackage(order, OrderConstant.GoodsPackageType.EXPRESS);
        if(dto.getThirdShip()) {
            orderPackage.setThirdShip(dto.getThirdShip());
            this.modify(orderPackage);
        }
        //创建订单物流包裹的物流信息(内部调用)
        orderPackageExpressService.create(orderPackage, dto);
        return orderPackage;
    }

    @Transactional
    @Override
    public OrderPackage expressShipForImport(Long shopId, BranchShipVO importRow) {
        Order order = orderService.loadByShopIdAndOrderNo(shopId, importRow.getOrderCode().replaceAll("\\s*", ""), true);
        //如果是无效订单，则不能发货
        if (2 == order.getMarketingType() && !order.getEffective()) {
            throw new RRException("拼团订单只有组团成功之后才能发货");
        }

        if (OrderConstant.ShipStatus.ALREADY_SHIP.equals(order.getShipStatus())) {
            throw new RRException(OrderException.SHIP_REPEAT);
        }

        //自提订单不要用物流发货
        if (order.getShipmentMode().equals(OrderConstant.ShipmentMode.PICK_UP)) {
            throw new RRException(OrderException.PICK_UP_ORDER_NOT_EXPRESS);
        }

        //创建订单包裹
        OrderPackage orderPackage = createOrderPackage(order, OrderConstant.GoodsPackageType.EXPRESS);
        //创建订单物流包裹的物流信息(内部调用)
        ExpressShipDTO dto = new ExpressShipDTO();
        SystemLogisticsCompanyEntity systemLogisticsCompanyEntity = systemLogisticsCompanyService.loadByName(importRow.getExpressName());
        dto.setExpressCode(systemLogisticsCompanyEntity==null?"无":systemLogisticsCompanyEntity.getLogisticsCode());
        dto.setExpressName(systemLogisticsCompanyEntity==null?"无":systemLogisticsCompanyEntity.getCompany());
        dto.setLogisticCode(importRow.getLogisticCode());
        orderPackageExpressService.create(orderPackage, dto);
        //创建包裹明细
        createPackageItemsByOrder(orderPackage, order);

        //订单运费入账
        if (order.getRealFreight().compareTo(BigDecimal.ZERO) > 0) {
            shopGainsBillService.inBill(order.getShopId(),
                    ShopGainsConstant.InnerMode.FREIGHT,
                    order.getRealFreight(),
                    String.format("订单：%s,运费入账：%s元", order.getOrderCode(), order.getRealFreight().toString()), order.getOrderCode());
        }

        return orderPackage;
    }

    @Override
    @DistributedLock(lockNamePre = LockPrefixConstant.PART_EXPRESS_SHIP, argNum = 2,param = "orderId")
    @Transactional(rollbackFor = Exception.class)
    public OrderPackage partExpressShip(Long shopId, ExpressShipDTO dto) {
        if(dto.getShipItems().size()==0)
        {
            throw new RRException("分包发货必须要选择发货的明细");
        }
        Order order = orderService.loadByShopIdAndId(shopId, dto.getOrderId(), true);
        //如果是无效订单，则不能发货
        OrderPackage orderPackage = buildOrderPackage(dto, order);
        //创建包裹明细
        createPackageItemsByOrder(orderPackage, order, dto);

        //订单运费入账
        if (OrderConstant.ShipStatus.ALREADY_SHIP.equals(order.getShipStatus()) &&  order.getRealFreight().compareTo(BigDecimal.ZERO) > 0) {
            shopGainsBillService.inBill(order.getShopId(),
                    ShopGainsConstant.InnerMode.FREIGHT,
                    order.getRealFreight(),
                    String.format("订单：%s,运费入账：%s元", order.getOrderCode(), order.getRealFreight().toString()), order.getOrderCode());
        }

        return orderPackage;
    }

    @Override
    public List<OrderPackage> loadListByOrderId(Long orderId) {
        return this.baseMapper.selectList(new LambdaQueryWrapper<OrderPackage>().eq(OrderPackage::getOrderId,orderId));
    }

    @Override
    public Order receiptPackage(Long userId, ExpressShipDTO dto) {
        Order order = orderService.loadByUserIdAndId(userId, dto.getOrderId(), true);
        if (OrderConstant.ShipStatus.NO_SHIP.equals(order.getShipStatus())) {
            //未发货不能收货
            throw new RRException(OrderException.SHIP_NOT_COMPLETE);
        }

        if (OrderConstant.ReceiptStatus.COMPLETE.equals(order.getReceiptStatus())) {
            //收货已完成,不要重复收货
            throw new RRException(OrderException.RECEIPT_REPEAT);
        }

        OrderPackage orderPackage = this.loadByOrderIdAndPackageId(order.getId(), dto.getPackageId(),true);
        updateReceiptStats(orderPackage, order);
        return order;
    }

    /**
     * 自提订单手动备货
     *
     * @param shopId
     * @param dto
     * @return
     */
    @Transactional
    @Override
    public OrderPackage pickupShip(Long shopId, ExpressShipDTO dto) {

        Order order = orderService.loadByShopIdAndId(shopId, dto.getOrderId(), true);
        //如果是无效订单，则不能发货
        if (2 == order.getMarketingType() && !order.getEffective()) {
            throw new RRException("拼团订单只有组团成功之后才能备货");
        }
        return pickupShip(order, dto.getRemark());
    }


    /**
     * 自提订单自动备货
     *
     * @param order
     * @return
     */
    @Transactional
    @Override
    public OrderPackage autoPickupShip(Order order) {
        if (order.getMarketingType() == 2) {
            throw new RRException("拼团订单不能自动备货");
        }

        if (!OrderConstant.ShipStatus.NO_SHIP.equals(order.getShipStatus())) {
            throw new RRException("只有没有备货的订单才可以自动备货");
        }
        return pickupShip(order, "");
    }


    /**
     * 用户收货物流订单
     *
     * @param userId
     * @param dto
     * @return
     */
    @Transactional
    @Override
    public Order receipt(Long userId, ExpressShipDTO dto) {
        Order order = orderService.loadByUserIdAndId(userId, dto.getOrderId(), true);
        if (OrderConstant.ReceiptStatus.COMPLETE.equals(order.getReceiptStatus())) {
            //收货已完成,不要重复收货
            throw new RRException(OrderException.RECEIPT_REPEAT);
        }
        if (!OrderConstant.TransactionStatus.WAIT_RECEIPT.equals(order.getTransactionStatus())) {
            //只有待收货的订单才可能全部收货
            throw new RRException("只有待收货的订单才可能全部收货");
        }

        updateReceiptStats(order);
        return order;
    }


    /**
     * 修改收货装态（包裹的，订单的，子订单的）
     *
     * @param order
     */
    private Order updateReceiptStats(Order order) {
        SaleConfig config = saleConfigService.getConfig();
        Integer autoCommentProcessDays = 7;
        Integer autoCloseRightsProcessDays = 15;
        if (config != null) {
            autoCommentProcessDays = config.getAutoCommentProcessDays();
            autoCloseRightsProcessDays = config.getAutoCloseRightsProcessDays();
        }

        List<OrderPackage> orderPackages = loadListByOrderId(order.getId());
        orderPackages.forEach(orderPackage->{
            orderPackage.setReceiptTime(new Date());
            orderPackage.setGoodsPackageStatus(OrderConstant.GoodsPackageStatus.RECEIPTED);
            this.modify(orderPackage);
        });


        List<ChildOrder> childOrderList = order.getChildOrderList(true);
        for (ChildOrder childOrder : childOrderList) {
            childOrder.setReceiptStatus(OrderConstant.ReceiptStatus.COMPLETE);
            childOrder.setTransactionStatus(OrderConstant.TransactionStatus.COMPLETE);
            childOrder.setReceiptedNum(childOrder.getReceiptedNum());
            childOrder.setFactReceiptTime(System.currentTimeMillis());
            childOrder.setLastEndTime(OrderConstant.getTomorrowAndDayTimestamp(System.currentTimeMillis(), autoCloseRightsProcessDays));
            childOrder.setLastCommentTime(OrderConstant.getTomorrowAndDayTimestamp(System.currentTimeMillis(), autoCommentProcessDays));
            childOrderService.modify(childOrder);
        }

        order.setReceiptStatus(OrderConstant.ReceiptStatus.COMPLETE);
        order.setTransactionStatus(OrderConstant.TransactionStatus.COMPLETE);
        order.setLastReceiptTime(System.currentTimeMillis());
        order.setCompleteTime(System.currentTimeMillis());
        orderService.modify(order);
        return order;

    }


    /**
     * 修改物流信息
     *
     * @param shopId
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public OrderPackage expressUpdate(Long shopId, ExpressShipDTO dto) {

        Order order = orderService.loadByShopIdAndId(shopId, dto.getOrderId(), true);
        if (OrderConstant.ReceiptStatus.COMPLETE.equals(order.getReceiptStatus())) {
            throw new RRException(OrderException.RECEIPT_COMPLETE);
        }

        OrderPackage orderPackage = this.loadByOrderIdAndPackageId(order.getId(), dto.getPackageId(),true);
        OrderPackageExpress orderPackageExpress = orderPackage.loadExpress();
        if (ObjectUtil.isNotNull(orderPackageExpress.getLastQueryTime())
                && !orderPackageExpress.getLogisticCode().equals(dto.getLogisticCode())) {
            orderPackageExpress.setLastQueryTime(0L);
        }
        orderPackageExpress.setExpressCode(dto.getExpressCode());
        orderPackageExpress.setExpressName(dto.getExpressName());
        orderPackageExpress.setLogisticCode(dto.getLogisticCode());
        orderPackageExpressService.modify(orderPackageExpress);
        return orderPackage;
    }

    @Override
    public OrderPackage loadByOrderIdAndPackageId(Long orderId, Long packageId, boolean tw) {
        OrderPackage one = this.getOne(new LambdaQueryWrapper<OrderPackage>()
                .eq(OrderPackage::getOrderId, orderId)
                .eq(OrderPackage::getId, packageId)
                .last("limit 1"));
        if (one == null && tw) {
            throw new RRException(OrderException.PACKAGE_NOT_EXISTS);
        }
        return one;
    }

    @Override
    public OrderPackage loadByOrderId(Long orderId, boolean tw) {
        OrderPackage one = this.getOne(new LambdaQueryWrapper<OrderPackage>()
                .eq(OrderPackage::getOrderId, orderId)
                .last("limit 1"));
        if (one == null && tw) {
            throw new RRException(OrderException.PACKAGE_NOT_EXISTS);
        }
        return one;
    }

    /**
     * 核销自提
     *
     * @param shopId
     * @param dto
     */
    @Transactional
    @Override
    public Order verification(Long shopId, ExpressShipDTO dto) {
        OrderPackagePickup orderPackagePickup = orderPackagePickupService.loadByVerification(dto.getVerification());
        if (orderPackagePickup == null) {
            //核销码不存在
            throw new RRException(OrderException.VERIFICATION_CODE_NOT_EXISTS);
        }

        OrderPackage orderPackage = this.baseMapper.selectById(orderPackagePickup.getGoodsPackageId());
        if (orderPackage == null) {
            //包裹不存在
            throw new RRException(OrderException.ORDER_PACKAGE_NOT_EXISTS);
        }

        Order order = orderService.loadByShopIdAndId(shopId, orderPackage.getOrderId(), true);

        if (!OrderConstant.ShipStatus.ALREADY_SHIP.equals(order.getShipStatus())) {
            //未发货不能收货
            throw new RRException(OrderException.SHIP_NOT_COMPLETE);
        }

        if (OrderConstant.ReceiptStatus.COMPLETE.equals(order.getReceiptStatus())) {
            //收货已完成,不要重复收货
            throw new RRException(OrderException.RECEIPT_REPEAT);
        }

        //核销状态修改
        orderPackagePickup.setVerificationTime(new Date());
        orderPackagePickup.setVerificationStatus(true);
        orderPackagePickup.setVerificationRole(OrderConstant.VerificationRole.Admin);
        orderPackagePickupService.modify(orderPackagePickup);

        //修改包裹收货状态
        updateReceiptStats(orderPackage, order);
        return order;
    }

    /**
     * 查询需要自动收货的包裹
     * 条件：
     * 1、待收货
     * 2、有自动收货过期时间
     * 3、是物流包裹
     * 4、当前时间过了自动收货时间
     *
     * @return
     */
    @Override
    public List<OrderPackage> needAutoReceipt() {
        return this.list(new LambdaQueryWrapper<OrderPackage>()
                .eq(OrderPackage::getGoodsPackageStatus, OrderConstant.GoodsPackageStatus.WAIT_RECEIPT)
                .gt(OrderPackage::getReceiptExpireTime, 0)
                .gt(OrderPackage::getGoodsPackageType, OrderConstant.GoodsPackageType.EXPRESS.getCode())
                .le(OrderPackage::getReceiptExpireTime, System.currentTimeMillis()));
    }

    /**
     * 查询需要自动自提收货包裹
     * 条件：
     * 1、待收货
     * 2、有自动收货过期时间
     * 3、是自提包裹
     * 4、当前时间过了自动自提收货时间
     *
     * @return
     */
    @Override
    public List<OrderPackage> needAutoPickup() {
        return this.list(new LambdaQueryWrapper<OrderPackage>()
                .eq(OrderPackage::getGoodsPackageStatus, OrderConstant.GoodsPackageStatus.WAIT_RECEIPT.getCode())
                .eq(OrderPackage::getGoodsPackageType, OrderConstant.GoodsPackageType.PICKUP.getCode())
                .gt(OrderPackage::getReceiptExpireTime, 0)
                .le(OrderPackage::getReceiptExpireTime, System.currentTimeMillis()));
    }

    /**
     * 自动收货
     *
     * @param orderPackage
     */
    @Transactional
    @Override
    public void autoReceipt(OrderPackage orderPackage) {
        Order order = orderPackage.loadOrder();
        if (!OrderConstant.ShipStatus.ALREADY_SHIP.equals(order.getShipStatus())) {
            throw new RRException("没有发货不能自动收货");
        }

        if (OrderConstant.ReceiptStatus.COMPLETE.equals(order.getReceiptStatus())) {
            throw new RRException("已收货不能自动收货");
        }

        updateReceiptStats(orderPackage, order);
    }

    /**
     * 自动核销
     *
     * @param orderPackage
     */
    @Override
    @Transactional
    public void autoPickupReceipt(OrderPackage orderPackage) {


        Order order = orderPackage.loadOrder();
        //未发货不能收货
        if (!OrderConstant.ShipStatus.ALREADY_SHIP.equals(order.getShipStatus())) {
            throw new RRException("没有备货不能自动核销");
        }

        if (OrderConstant.ReceiptStatus.COMPLETE.equals(order.getReceiptStatus())) {
            throw new RRException("交易完成不能再自动核销");
        }

        OrderPackagePickup orderPackagePickup = orderPackage.loadPickup();
        orderPackagePickup.setVerificationTime(new Date());
        orderPackagePickup.setVerificationStatus(true);
        orderPackagePickup.setVerificationRole(OrderConstant.VerificationRole.SYSTEM);
        orderPackagePickupService.modify(orderPackagePickup);

        updateReceiptStats(orderPackage, order);
    }

    /**
     * 物流跟踪
     *
     * @param orderId
     * @return
     */
    @Override
    public OrderPackageExpress expressSelect(Long orderId,Long packageId) {
        OrderPackage obj = this.loadByOrderIdAndPackageId(orderId, packageId, true);
        if (obj == null) {
            return null;
        }

        if (OrderConstant.GoodsPackageType.PICKUP.equals(obj.getGoodsPackageType())) {
            return null;
        }

        OrderPackageExpress orderPackageExpress = obj.loadExpress();
        if (orderPackageExpress.isAbleSelect()) {
//            String result = orderService.queryExpressExpNo(orderPackageExpress.getLogisticCode());
            Order order = obj.loadOrder();
            String result = orderService.queryExpressExpNo(orderPackageExpress.getLogisticCode(), order.getMobile());
            orderPackageExpress.setQueryResult(result);
            orderPackageExpress.setLastQueryTime(System.currentTimeMillis());
            orderPackageExpressService.modify(orderPackageExpress);
        }
        return orderPackageExpress;
    }

    @Override
    public Order loadOrderByVerification(Long shopId, ExpressShipDTO dto) {
        OrderPackagePickup orderPackagePickup = orderPackagePickupService.loadByVerification(dto.getVerification());
        if (orderPackagePickup == null) {
            //核销码不存在
            throw new RRException(OrderException.VERIFICATION_CODE_NOT_EXISTS);
        }

        OrderPackage orderPackage = this.baseMapper.selectById(orderPackagePickup.getGoodsPackageId());
        if (orderPackage == null) {
            //包裹不存在
            throw new RRException(OrderException.VERIFICATION_CODE_NOT_EXISTS);
        }

        return orderService.loadByShopIdAndId(shopId, orderPackage.getOrderId(), true);

    }



    /**
     * 修改收货装态（包裹的，订单的，子订单的）
     *
     * @param orderPackage
     * @param order
     */
    private Order updateReceiptStats(OrderPackage orderPackage, Order order) {
        SaleConfig config = saleConfigService.getConfig();
        Integer autoCommentProcessDays = 7;
        Integer autoCloseRightsProcessDays = 15;
        if (config != null) {
            autoCommentProcessDays = config.getAutoCommentProcessDays();
            autoCloseRightsProcessDays = config.getAutoCloseRightsProcessDays();
        }
        orderPackage.setReceiptTime(new Date());
        orderPackage.setGoodsPackageStatus(OrderConstant.GoodsPackageStatus.RECEIPTED);
        this.modify(orderPackage);

        List<OrderPackageItem> orderPackageItems = orderPackageItemService.loadOrderPackageItem(orderPackage.getId());
        boolean allReceipted = true;
        List<ChildOrder> childOrderList = order.getChildOrderList(true);
        for (ChildOrder childOrder : childOrderList) {
            Optional<OrderPackageItem> first = orderPackageItems.stream().filter(o -> o.getChildOrderId().equals(childOrder.getId()) && o.getOrderId().equals(childOrder.getOrderId())).findFirst();
            if(!first.isPresent())
            {
                if(!childOrder.getNumber().equals(childOrder.getReceiptedNum()))
                {
                    allReceipted = false;
                }
                continue;
            }
            OrderPackageItem item  = first.get();
            Integer originalReceiptedNum = childOrder.getReceiptedNum();
            int currentReceiptedNum = originalReceiptedNum + item.getNumber();
            if (currentReceiptedNum > childOrder.getNumber()) {
                throw new RRException("收货数量不能超出购买商品的数量");
            }
            boolean isComplete = childOrder.getNumber().equals(currentReceiptedNum);
            if(isComplete) {
                childOrder.setReceiptStatus(OrderConstant.ReceiptStatus.COMPLETE);
                childOrder.setTransactionStatus(OrderConstant.TransactionStatus.COMPLETE);
                childOrder.setReceiptedNum(currentReceiptedNum);
                childOrder.setFactReceiptTime(System.currentTimeMillis());
                childOrder.setLastEndTime(OrderConstant.getTomorrowAndDayTimestamp(System.currentTimeMillis(), autoCloseRightsProcessDays));
                childOrder.setLastCommentTime(OrderConstant.getTomorrowAndDayTimestamp(System.currentTimeMillis(), autoCommentProcessDays));
            }
            else
            {
                childOrder.setReceiptStatus(OrderConstant.ReceiptStatus.PART);
                childOrder.setTransactionStatus(OrderConstant.TransactionStatus.PART_RECEIPT);
                childOrder.setReceiptedNum(currentReceiptedNum);
                childOrder.setFactReceiptTime(System.currentTimeMillis());
                allReceipted = false;
            }
            childOrderService.modify(childOrder);

        }

        if(allReceipted) {
            order.setReceiptStatus(OrderConstant.ReceiptStatus.COMPLETE);
            order.setTransactionStatus(OrderConstant.TransactionStatus.COMPLETE);
            order.setLastReceiptTime(System.currentTimeMillis());
            order.setCompleteTime(System.currentTimeMillis());
        }
        else
        {
            order.setReceiptStatus(OrderConstant.ReceiptStatus.PART);
            order.setTransactionStatus(OrderConstant.TransactionStatus.PART_RECEIPT);
        }
        orderService.modify(order);
        return order;

    }


    /**
     * 创建订单包裹
     *
     * @param order
     * @param type
     * @return
     */
    private OrderPackage createOrderPackage(Order order, OrderConstant.GoodsPackageType type) {
        OrderPackage orderPackage = new OrderPackage();
        orderPackage.setGoodsPackageType(type);
        orderPackage.setOrderId(order.getId());
        orderPackage.setOrderCode(order.getOrderCode());
        orderPackage.setGoodsPackageStatus(OrderConstant.GoodsPackageStatus.WAIT_RECEIPT);
        Long receiptExpireTime = 0L;
        if (OrderConstant.GoodsPackageType.PICKUP.equals(type)) {
            LogisticsConfig logisticsConfig = logisticsConfigService.getLogisticsConfig(order.getShopId());
            if (logisticsConfig != null && logisticsConfig.getAblePickupExpired()) {
                receiptExpireTime = OrderConstant.getTomorrowAndDayTimestamp(System.currentTimeMillis(), logisticsConfig.getPickupExpired());
            }
        } else {
            SaleConfig config = saleConfigService.getConfig();
            int addDay = 10;
            if (config != null) {
                addDay = config.getAutoReceiptProcessDays();
            }
            receiptExpireTime = OrderConstant.getTomorrowAndDayTimestamp(System.currentTimeMillis(), addDay);
        }
        orderPackage.setReceiptExpireTime(receiptExpireTime);
        orderPackage.setReceiptTime(null);
        orderPackage.setUseDelayReceipt(false);
        this.create(orderPackage);


        return orderPackage;
    }

    private void createPackageItemsByOrder(OrderPackage orderPackage, Order order, ExpressShipDTO dto) {
        List<ChildOrder> childOrderList = order.getChildOrderList(true);
        boolean allShip = true;
        for (ChildOrder childOrder : childOrderList) {
            ShipItemDTO item = getShipItem(childOrder, dto.getShipItems());
            if (ObjectUtil.isNull(item)) {
                if(!childOrder.getNumber().equals(childOrder.getShipNum()))
                {
                    allShip = false;
                }
                continue;
            }
            if(item.getShipNum()<=0)
            {
                throw new RRException("发货数量必须大于零");
            }
            OrderPackageItem orderPackageItem = new OrderPackageItem();
            orderPackageItem.setChildOrderId(childOrder.getId());
            orderPackageItem.setGoodsId(childOrder.getGoodsId());
            orderPackageItem.setGoodsImg(childOrder.getGoodsImg());
            orderPackageItem.setGoodsTitle(childOrder.getGoodsTitle());
            orderPackageItem.setGoodsPackageId(orderPackage.getId());
            orderPackageItem.setNumber(item.getShipNum());
            orderPackageItem.setSkuSetName(childOrder.getSkuSetName());
            orderPackageItem.setOrderId(order.getId());
            orderPackageItemService.create(orderPackageItem);


            Integer originalShipNum = childOrder.getShipNum();
            int currentShipNum = originalShipNum + item.getShipNum();
            if (currentShipNum > childOrder.getNumber()) {
                throw new RRException("发货数量不能超出购买商品的数量");
            }
            boolean isComplete = childOrder.getNumber().equals(currentShipNum);

            childOrder.setShipNum(currentShipNum);
            childOrder.setTransactionStatus(isComplete ? OrderConstant.TransactionStatus.WAIT_RECEIPT : OrderConstant.TransactionStatus.PART_SHIP);
            childOrder.setShipTime(orderPackage.getCreateTime().getTime());
            childOrder.setShipStatus(isComplete ? OrderConstant.ShipStatus.ALREADY_SHIP : OrderConstant.ShipStatus.PART_SHIP);
            childOrderService.modify(childOrder);

            if(!isComplete)
            {
                allShip = false;
            }
        }


        //订单改变发货状态
        order.setLastShipTime(orderPackage.getCreateTime().getTime());
        order.setTransactionStatus(allShip?OrderConstant.TransactionStatus.WAIT_RECEIPT: OrderConstant.TransactionStatus.PART_SHIP);
        order.setShipStatus(allShip?OrderConstant.ShipStatus.ALREADY_SHIP: OrderConstant.ShipStatus.PART_SHIP);
        orderService.modify(order);


    }


    private ShipItemDTO getShipItem(ChildOrder childOrder, List<ShipItemDTO> dtos) {
        Optional<ShipItemDTO> first = dtos.stream().filter(o -> o.getChildOrderId().equals(childOrder.getId()) && o.getOrderId().equals(childOrder.getOrderId())).findFirst();
        if (first.isPresent()) {
            return first.get();
        }
        return null;
    }

    /**
     * 创建包裹明细
     *
     * @param orderPackage
     * @param order
     */
    private void createPackageItemsByOrder(OrderPackage orderPackage, Order order) {
        List<ChildOrder> childOrderList = order.getChildOrderList(true);
        for (ChildOrder childOrder : childOrderList) {
            OrderPackageItem orderPackageItem = new OrderPackageItem();
            orderPackageItem.setChildOrderId(childOrder.getId());
            orderPackageItem.setGoodsId(childOrder.getGoodsId());
            orderPackageItem.setGoodsImg(childOrder.getGoodsImg());
            orderPackageItem.setGoodsTitle(childOrder.getGoodsTitle());
            orderPackageItem.setGoodsPackageId(orderPackage.getId());
            orderPackageItem.setNumber(childOrder.getNumber());
            orderPackageItem.setSkuSetName(childOrder.getSkuSetName());
            orderPackageItem.setOrderId(order.getId());
            orderPackageItemService.create(orderPackageItem);

            /**
             * 因这里只做一次性的全量发货，所有可以马上改变所有子订单的发货状态
             */
            childOrder.setShipNum(childOrder.getNumber());
            childOrder.setTransactionStatus(OrderConstant.TransactionStatus.WAIT_RECEIPT);
            childOrder.setShipTime(orderPackage.getCreateTime().getTime());
            childOrder.setShipStatus(OrderConstant.ShipStatus.ALREADY_SHIP);
            childOrderService.modify(childOrder);
        }
        //所有订单改变发货状态


        //订单改变发货状态
        order.setLastShipTime(orderPackage.getCreateTime().getTime());
        order.setTransactionStatus(OrderConstant.TransactionStatus.WAIT_RECEIPT);
        order.setShipStatus(OrderConstant.ShipStatus.ALREADY_SHIP);
        orderService.modify(order);
    }


    /**
     * 内部调用自提订单备货
     *
     * @param order
     * @param remark
     * @return
     */
    private OrderPackage pickupShip(Order order, String remark) {
        if (OrderConstant.ShipStatus.ALREADY_SHIP.equals(order.getShipStatus())) {
            throw new RRException(OrderException.STOCK_UP_REPEAT);
        }
        //物流订单不要用自提备货
        if (order.getShipmentMode().equals(OrderConstant.ShipmentMode.EXPRESS)) {
            throw new RRException(OrderException.EXPRESS_NOT_PICK_UP_ORDER);
        }

        //创建订单包裹
        OrderPackage orderPackage = createOrderPackage(order, OrderConstant.GoodsPackageType.PICKUP);
        //创建订单自提包裹的信息
        orderPackagePickupService.create(orderPackage, remark);
        //创建包裹明细
        createPackageItemsByOrder(orderPackage, order);

        return orderPackage;
    }


}
